import {
  Color,
  PolylineArrowMaterialProperty,
  PolygonHierarchy,
  Cartesian3,
  Cartesian4,
  PostProcessStage,
  HeadingPitchRange,
  CallbackProperty,
  Math as cesiumMath,
  Rectangle,
  NearFarScalar,
  ColorMaterialProperty,
  Transforms,
  Matrix4,
  Cartographic,
  Cartesian2,
  ImageMaterialProperty,
  LineFlowMaterialProperty,
  Ellipsoid,
} from "cesium";

/**
 * @description: 产生随机点
 * @param {*} position：中心点坐标
 * @param {*} num：随机点数量
 * @return {*}
 */
export const generateRandomPosition = (position, num) => {
  let list = [];
  for (let i = 0; i < num; i++) {
    // random产生的随机数范围是0-1，需要加上正负模拟
    let lon = position[0] + Math.random() * 0.04 * (i % 2 == 0 ? 1 : -1);
    let lat = position[1] + Math.random() * 0.04 * (i % 2 == 0 ? 1 : -1);
    list.push([lon, lat]);
  }
  return list;
};

/**
 * @description: 竖直随机飞线初始化
 * @param {*} _viewer
 * @param {*} _center ：中心点
 * @param {*} _num ：数量
 * @return {*}
 */
export const lineFlowInit = (_viewer, _center, _num) => {
  let _positions = generateRandomPosition(_center, _num);
  _positions.forEach((item) => {
    console.log("item------------------");
    console.log(item);

    // 经纬度
    let start_lon = item[0];
    let start_lat = item[1];

    let startPoint = new Cartesian3.fromDegrees(start_lon, start_lat, 0);

    // 随机高度
    let height = 5000 * Math.random();
    let endPoint = new Cartesian3.fromDegrees(start_lon, start_lat, height);
    let linePositions = [];
    linePositions.push(startPoint);
    linePositions.push(endPoint);
    _viewer.entities.add({
      polyline: {
        positions: linePositions,
        material: new LineFlowMaterialProperty({
          color: new Color(1.0, 1.0, 0.0, 0.8),
          speed: 15 * Math.random(),
          percent: 0.1,
          gradient: 0.01,
        }),
      },
    });
  });
};

/**
 * @description: 抛物飞线效果初始化
 * @param {*} _viewer 当前viewer单独UI西安昂
 * @param {*} _num :每条线上的飞线数量
 * @return {*}
 */

export const parabolaFlowInit = (_viewer, _num) => {
  let _center = [113.26826367882262, 23.1381520242615];
  let _positions = [
    [113.244807, 23.144568],
    [113.312938, 23.129189],
    [113.300935, 23.143839],
    [113.822965, 23.283922],
    [113.526148, 22.80173],
    [113.344075, 23.145948],
    [113.271455, 23.112136],
    [113.269087, 23.202798],
    [113.376456, 23.124494],
    [113.245139, 23.087279],
    [113.278683, 23.13052],
    [113.318869, 23.166055],
    [113.316116, 23.098584],
    [113.383898, 22.948387],
    [113.244873, 23.282587],
    [113.404638, 23.385404],
    [113.358788, 23.294487],
    [113.299237, 23.347044],
    [113.275543, 23.154549],
    [113.373932, 23.112827],
    [113.605399, 23.12292],
    [113.215333, 23.385054],
    [113.273491, 23.436141],
    [113.321506, 23.436262],
    [113.181741, 23.454722],
    [113.870389, 23.771835],
    [113.589175, 23.543664],
    [113.418954, 23.622731],
    [113.678424, 23.63371],
    [113.431474, 23.169309],
    [113.495299, 23.150867],
    [113.277926, 23.080252],
    [113.273426, 23.127829],
    [113.525878, 23.059446],
    [113.457836, 23.107109],
    [113.45653, 23.105514],
    [113.428128, 23.076534],
    [113.273836, 23.170145],
    [113.218163, 23.395116],
    [113.106668, 23.335404],
    [113.060928, 23.395699],
    [113.291789, 23.556733],
    [113.280284, 23.458391],
    [113.591187, 23.549468],
    [113.487265, 22.969647],
    [113.733069, 23.722228],
    [113.824317, 23.284843],
    [113.78594, 23.418958],
    [113.616589, 23.28853],
    [113.792079, 23.178072],
    [113.894637, 23.416335],
    [113.78524, 23.488541],
  ];
  _positions.forEach((item) => {
    let _siglePositions = parabola(_center, item, 5000);
    // 创建飞线
    for (let i = 0; i < _num; i++) {
      _viewer.entities.add({
        polyline: {
          positions: _siglePositions,
          material: new LineFlowMaterialProperty({
            color: new Color(1.0, 1.0, 0.0, 0.8),
            speed: 1 * Math.random(),
            percent: 0.1,
            gradient: 0.01,
          }),
        },
      });
    }
    // 创建轨迹线
    _viewer.entities.add({
      polyline: {
        positions: _siglePositions,
        material: new PolylineArrowMaterialProperty(
          new Color(1.0, 1.0, 0.0, 0.5)
        ),
      },
    });
  });
};

/**
 * @description: 抛物线构造函数
 * @param {startPositionstartPosition}  开始点位
 * @param {endPosition} endPosition 结束点位
 * @param {height} height 抛物线高度
 * @return {*}
 */
export const parabola = (
  startPosition,
  endPosition,
  height = 5000,
  count = 50
) => {
  //方程 y=-(4h/L^2)*x^2+h h:顶点高度 L：横纵间距较大者
  let result = [];
  height = Math.max(+height, 100);
  count = Math.max(+count, 50);
  let diffLon = Math.abs(startPosition[0] - endPosition[0]);
  let diffLat = Math.abs(startPosition[1] - endPosition[1]);
  let L = Math.max(diffLon, diffLat);
  let dlt = L / count;
  if (diffLon > diffLat) {
    //base on lon
    let delLat = (endPosition[1] - startPosition[1]) / count;
    if (startPosition[0] - endPosition[0] > 0) {
      dlt = -dlt;
    }
    for (let i = 0; i < count; i++) {
      let h =
        height -
        (Math.pow(-0.5 * L + Math.abs(dlt) * i, 2) * 4 * height) /
          Math.pow(L, 2);
      let lon = startPosition[0] + dlt * i;
      let lat = startPosition[1] + delLat * i;
      let point = new Cartesian3.fromDegrees(lon, lat, h);
      result.push(point);
    }
  } else {
    //base on lat
    let delLon = (endPosition[0] - startPosition[0]) / count;
    if (startPosition[1] - endPosition[1] > 0) {
      dlt = -dlt;
    }
    for (let i = 0; i < count; i++) {
      let h =
        height -
        (Math.pow(-0.5 * L + Math.abs(dlt) * i, 2) * 4 * height) /
          Math.pow(L, 2);
      let lon = startPosition[0] + delLon * i;
      let lat = startPosition[1] + dlt * i;
      let point = new Cartesian3.fromDegrees(lon, lat, h);
      result.push(point);
    }
  }
  return result;
};

/**
 * circleDiffusion：圆扩散
 * 参考gitee上的ts代码
 */

// 圆扩散
export class CircleDiffusion {
  constructor(viewer) {
    this.viewer = viewer;
    this.lastStageList = [];
    // js语法的每行结尾的“分号”可写可不写
  }
  add(position, scanColor, maxRadius, duration) {
    this.lastStageList.push(
      this.showCircleScan(position, scanColor, maxRadius, duration)
    );
  }
  clear() {
    this.lastStageList.forEach((ele) => {
      this.clearScanEffects(ele);
    });
    this.lastStageList = [];
  }
  /**
   * 圆扩散
   * @param {*} position  扫描中心 如[117.270739,31.84309,32]
   * @param {*} scanColor 扫描颜色 如"rgba(0,255,0,1)"
   * @param {*} maxRadius 扫描半径，单位米 如1000米
   * @param {*} duration 持续时间，单位毫秒 如4000
   */
  showCircleScan(position, scanColor, maxRadius, duration) {
    const cartographicCenter = new Cartographic(
      cesiumMath.toRadians(position[0]),
      cesiumMath.toRadians(position[1]),
      position[2]
    );
    scanColor = new Color.fromCssColorString(scanColor);
    const lastStage = this._addCircleScanPostStage(
      cartographicCenter,
      maxRadius,
      scanColor,
      duration
    );
    return lastStage;
  }
  /**
   * 添加扩散效果扫描线
   * @param {*} cartographicCenter  扫描中心
   * @param {*} maxRadius 扫描半径
   * @param {*} scanColor  扫描颜色
   * @param {*} duration  持续时间
   */
  _addCircleScanPostStage(cartographicCenter, maxRadius, scanColor, duration) {
    const _Cartesian3Center = Cartographic.toCartesian(cartographicCenter);
    const _Cartesian4Center = new Cartesian4(
      _Cartesian3Center.x,
      _Cartesian3Center.y,
      _Cartesian3Center.z,
      1
    );
    const _CartograhpicCenter1 = new Cartographic(
      cartographicCenter.longitude,
      cartographicCenter.latitude,
      cartographicCenter.height + 500
    );
    const _Cartesian3Center1 = Cartographic.toCartesian(_CartograhpicCenter1);
    const _Cartesian4Center1 = new Cartesian4(
      _Cartesian3Center1.x,
      _Cartesian3Center1.y,
      _Cartesian3Center1.z,
      1
    );
    const _time = new Date().getTime();
    const _scratchCartesian4Center = new Cartesian4();
    const _scratchCartesian4Center1 = new Cartesian4();
    const _scratchCartesian3Normal = new Cartesian3();
    const _this = this;
    const ScanPostStage = new PostProcessStage({
      fragmentShader: _this._getScanSegmentShader(),
      uniforms: {
        u_scanCenterEC: function () {
          const temp = Matrix4.multiplyByVector(
            _this.viewer.camera._viewMatrix,
            _Cartesian4Center,
            _scratchCartesian4Center
          );
          return temp;
        },
        u_scanPlaneNormalEC: function () {
          const temp = Matrix4.multiplyByVector(
            _this.viewer.camera._viewMatrix,
            _Cartesian4Center,
            _scratchCartesian4Center
          );
          const temp1 = Matrix4.multiplyByVector(
            _this.viewer.camera._viewMatrix,
            _Cartesian4Center1,
            _scratchCartesian4Center1
          );
          _scratchCartesian3Normal.x = temp1.x - temp.x;
          _scratchCartesian3Normal.y = temp1.y - temp.y;
          _scratchCartesian3Normal.z = temp1.z - temp.z;
          Cartesian3.normalize(
            _scratchCartesian3Normal,
            _scratchCartesian3Normal
          );
          return _scratchCartesian3Normal;
        },
        u_radius: function () {
          return (
            (maxRadius * ((new Date().getTime() - _time) % duration)) / duration
          );
        },
        u_scanColor: scanColor,
      },
    });
    this.viewer.scene.postProcessStages.add(ScanPostStage);
    return ScanPostStage;
  }
  /**
   * 扩散效果Shader
   */
  _getScanSegmentShader() {
    const inpram = 18;
    const scanSegmentShader =
      ` uniform sampler2D colorTexture;
          uniform sampler2D depthTexture;
          varying vec2 v_textureCoordinates;
          uniform vec4 u_scanCenterEC;
          uniform vec3 u_scanPlaneNormalEC;
          uniform float u_radius;
          uniform vec4 u_scanColor;
          vec4 toEye(in vec2 uv, in float depth){
            vec2 xy = vec2((uv.x * 2.0 - 1.0),(uv.y * 2.0 - 1.0));
            vec4 posInCamera = czm_inverseProjection * vec4(xy, depth, 1.0);
            posInCamera =posInCamera / posInCamera.w;
            return posInCamera;
          }
          vec3 pointProjectOnPlane(in vec3 planeNormal, in vec3 planeOrigin, in vec3 point){
              vec3 v01 = point - planeOrigin;
              float d = dot(planeNormal, v01) ;
              return (point - planeNormal * d);
          }
          float getDepth(in vec4 depth){
              float z_window = czm_unpackDepth(depth);
              z_window = czm_reverseLogDepth(z_window);
              float n_range = czm_depthRange.near;
              float f_range = czm_depthRange.far;
              return (2.0 * z_window - n_range - f_range) / (f_range - n_range);
          }
          void main(){
              gl_FragColor = texture2D(colorTexture, v_textureCoordinates);
              float depth = getDepth(texture2D(depthTexture, v_textureCoordinates));
              vec4 viewPos = toEye(v_textureCoordinates, depth);
              vec3 prjOnPlane = pointProjectOnPlane(u_scanPlaneNormalEC.xyz, u_scanCenterEC.xyz, viewPos.xyz);
              float dis = length(prjOnPlane.xyz - u_scanCenterEC.xyz);
              if(dis < u_radius){
                float f = 1.0 - abs(u_radius - dis) / u_radius;
                f = pow(f, float(` +
      inpram +
      `));
                gl_FragColor = mix(gl_FragColor,u_scanColor,f);
              }
              gl_FragColor.a = gl_FragColor.a / 2.0;
          }
        `;
    return scanSegmentShader;
  }
  /**
   * 清除特效对象
   * @param {*} lastStage 特效对象
   */
  clearScanEffects(lastStage) {
    this.viewer.scene.postProcessStages.remove(lastStage);
  }
}

/**
 * @Description： 立体雷达扫描效果
 * @viewer {Object} viewer对象
 * @radius {number} 圆角
 * @color {number} 颜色对象
 * @speed {number} 旋转速度
 * @position {Array} 经纬度坐标
 */
export const radarSolidScan = ({
  viewer,
  radius,
  color,
  speed,
  position,
} = {}) => {
  let thisData = {};
  thisData._viewer = options.viewer;
  // 半径
  thisData._radius = options.radius;
  // 扫描扇形颜色
  thisData._color = options.color;
  // 扫描速度
  thisData._speed = options.speed;
  // 中心点坐标经纬度
  thisData._cenLon = options.position[0];
  thisData._cenLat = options.position[1];
  // 先建立椭球体
  thisData._viewer.entities.add({
    position: new Cartesian3.fromDegrees(thisData._cenLon, thisData._cenLat),
    name: "立体雷达扫描",
    ellipsoid: {
      radii: new Cartesian3(
        thisData._radius,
        thisData._radius,
        thisData._radius
      ),
      material: thisData._color,
      outline: true,
      outlineColor: thisData._color,
      outlineWidth: 1,
    },
  });

  let heading = 0,
    positionArr = calculatePane(
      thisData._cenLon,
      thisData._cenLat,
      1000.0,
      heading
    );
  // 每一帧刷新时调用
  thisData._viewer.clock.onTick.addEventListener(() => {
    heading += thisData._speed;
    positionArr = calculatePane(
      thisData._cenLon,
      thisData._cenLat,
      1000.0,
      heading
    );
  });

  // 创建1/4圆形立体墙
  let radarWall = thisData._viewer.entities.add({
    wall: {
      positions: new CallbackProperty(() => {
        return Cartesian3.fromDegreesArrayHeights(positionArr);
      }, false),
      material: Color.RED,
    },
  });

  // 计算平面扫描范围
  function calculatePane(x1, y1, radius, heading) {
    var m = Transforms.eastNorthUpToFixedFrame(Cartesian3.fromDegrees(x1, y1));
    var rx = radius * Math.cos((heading * Math.PI) / 180.0);
    var ry = radius * Math.sin((heading * Math.PI) / 180.0);
    var translation = Cartesian3.fromElements(rx, ry, 0);
    var d = Matrix4.multiplyByPoint(m, translation, new Cartesian3());
    var c = Cartographic.fromCartesian(d);
    var x2 = cesiumMath.toDegrees(c.longitude);
    var y2 = cesiumMath.toDegrees(c.latitude);
    return calculateSector(x1, y1, x2, y2);
  }

  // 计算竖直扇形
  function calculateSector(x1, y1, x2, y2) {
    let positionArr = [];
    positionArr.push(x1);
    positionArr.push(y1);
    positionArr.push(0);
    var radius = Cartesian3.distance(
      Cartesian3.fromDegrees(x1, y1),
      Cartesian3.fromDegrees(x2, y2)
    );
    // 扇形是1/4圆，因此角度设置为0-90
    for (let i = 0; i <= 90; i++) {
      let h = radius * Math.sin((i * Math.PI) / 180.0);
      let r = Math.cos((i * Math.PI) / 180.0);
      let x = (x2 - x1) * r + x1;
      let y = (y2 - y1) * r + y1;
      positionArr.push(x);
      positionArr.push(y);
      positionArr.push(h);
    }
    return positionArr;
  }
};

/**
 * @name 动态圆扩散
 * @minR {number} 最小半径
 * @maxR {number} 最大半径
 * @deviationR {number} 每次增加半径大小
 * @position {Array} 经纬度
 */
export const dynamicCircle = ({ minR, maxR, deviationR, position } = {}) => {
  minR = minR ? minR : 100;
  let minData = minR;
  maxR = maxR ? maxR : 5000;
  deviationR = deviationR ? deviationR : 50;
  position = position ? position : [113.89263931497018, 22.76474442946943];
  function changeR1() {
    minR = minR + deviationR; //deviationR为每次圆增加的大小
    if (minR >= maxR) {
      minR = minData;
    }
    return minR;
  }
  function colorSet() {
    let x = 1 - minR / maxR;
    return Color.RED.withAlpha(x);
  }
  function changeR() {
    return minR;
  }
  let image = `./imgs/12.png`;
  let entity = viewer.entities.add({
    position: Cartesian3.fromDegrees(position[0], position[1]),
    name: "圆形",
    ellipse: {
      semiMinorAxis: new CallbackProperty(changeR, false),
      semiMajorAxis: new CallbackProperty(changeR1, false),
      material: new ImageMaterialProperty({
        repeat: new Cartesian2(1.0, 1.0),
        image: image,
        transparent: true,
        color: new CallbackProperty(colorSet, false),
      }),
      show: false,
      // material: new ColorMaterialProperty(new CallbackProperty(color,false)),
      outlineColor: Color.RED,
    },
  });
};

export const getCenterPosition = (viewer) => {
  let centerResult = viewer.camera.pickEllipsoid(
    new Cartesian2(
      viewer.canvas.clientWidth / 2,
      viewer.canvas.clientHeight / 2
    )
  );
  let curPosition = Ellipsoid.WGS84.cartesianToCartographic(centerResult);
  let curLongitude = (curPosition.longitude * 180) / Math.PI;
  let curLatitude = (curPosition.latitude * 180) / Math.PI;
  console.log({
    lon: curLongitude,
    lat: curLatitude,
  });
  return {
    lon: curLongitude,
    lat: curLatitude,
  };
};
